package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"syscall"
)

func mainRun() {
	var workDir, containerName, hostName string
	var volumns arrayFlags
	var tty bool
	fs := flag.NewFlagSet("run", flag.ExitOnError)
	fs.BoolVar(&DEBUG, "debug", false, "show debug info")
	fs.BoolVar(&tty, "tty", false, "allocate new tty")
	fs.StringVar(&workDir, "w", "", "image dir")
	fs.StringVar(&containerName, "name", "UUID(8)", "container name")
	fs.StringVar(&hostName, "h", DefaultHostName, "host name in container")
	fs.Var(&volumns, "v", "volumn")
	assert(fs.Parse(os.Args[2:]))

	if len(workDir) == 0 {
		fmt.Println("Missing -w param")
		os.Exit(1)
	}

	if fs.NArg() == 0 {
		fmt.Println("Missing command")
		os.Exit(1)
	}

	var err error
	workDir, err = filepath.Abs(workDir)
	assert(err)

	vols, mps := parseVolumnArgs(volumns)

	var config Config
	config.ID = UUID(16)
	config.Name = containerName
	config.Mounts.Volumns = vols
	for _, m := range mps {
		config.Mounts.Mounts = append(config.Mounts.Mounts, m)
	}
	config.ImageDir = workDir
	config.Tty = tty
	config.HostName = hostName

	// save config
	dir := path.Join(LibDir, "config")
	assert(os.MkdirAll(dir, 0755))
	configDir := path.Join(dir, config.ID+".json")
	f, err := os.Create(configDir)
	assert(err)
	defer func() {
		f.Close()
		os.Remove(configDir)
	}()
	assert(json.NewEncoder(f).Encode(config))
	f.Close()

	os.Clearenv()

	cmd := exec.Command("/proc/self/exe")
	cmd.Args = []string{cmd.Path, "_run", "-c", configDir}
	if DEBUG {
		cmd.Args = append(cmd.Args, "--debug")
	}
	cmd.Args = append(cmd.Args, fs.Args()...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Cloneflags: syscall.CLONE_NEWNS |
			syscall.CLONE_NEWUTS |
			syscall.CLONE_NEWPID,
		//syscall.CLONE_NEWNET,
		Unshareflags: syscall.CLONE_NEWNS,
		//UidMappings:  []syscall.SysProcIDMap{{ContainerID: 0, HostID: 0, Size: 1}},
		//GidMappings:  []syscall.SysProcIDMap{{ContainerID: 0, HostID: 0, Size: 1}},
	}
	assert(cmd.Run())
}
